#include "ConexionLDAP.h"

	ConexionLDAP::ConexionLDAP(int id, char* host, int port):Conexion(id,host,port){
		inicializar(host,port);
	}	

	void ConexionLDAP::insertar(Encolable* actual){
		char* dn; // fijarse de donde lo saco
		LDAPMod atts[actual->getCantidadDeCampos()];
		int i = 0;
		Nodo<CampoConfigurableSimple>* campoSimple = actual->getListaSimple().getPrimero();
		while(campoSimple){
			agregarAtributoSimple(&atts[i++], LDAP_MOD_ADD,campoSimple->getDato());		
			campoSimple = campoSimple->getSiguiente();
		}
		Nodo<CampoConfigurableMulti>* campoMulti = actual->getListaMulti().getPrimero();
		while(campoMulti){
			agregarAtributoMulti(&atts[i++], LDAP_MOD_ADD,campoMulti->getDato());		
			campoMulti = campoMulti->getSiguiente();
		}
		LDAPMod * campos = atts;
		agregar(dn,&campos);
	}


	void ConexionLDAP::modificar(Encolable* actual){
		char* dn;
		LDAPMod atts[actual->getCantidadDeCampos()];
		int i = 0;
		Nodo<CampoConfigurableSimple>* campoSimple = actual->getListaSimple().getPrimero();
		while(campoSimple){
			agregarAtributoSimple(&atts[i++], LDAP_MOD_REPLACE,campoSimple->getDato());		
			campoSimple = campoSimple->getSiguiente();
		}
		Nodo<CampoConfigurableMulti>* campoMulti = actual->getListaMulti().getPrimero();
		while(campoMulti){
			agregarAtributoMulti(&atts[i++], LDAP_MOD_REPLACE,campoMulti->getDato());		
			campoMulti = campoMulti->getSiguiente();
		}
		LDAPMod * campos = atts;
		agregar(dn,&campos);
	}

	void ConexionLDAP::eliminar(Encolable* actual){
		char* dn;
		borrar(dn);
	}


	void ConexionLDAP::agregarAtributoSimple(LDAPMod* att, int op, CampoConfigurableSimple campoSimple){
		att->mod_op = op;
		att->mod_type = campoSimple.getNombre();
		char *	valor = campoSimple.getValor();
		char** aux = &valor;
		att->mod_vals.modv_strvals = aux;
	}	

	void ConexionLDAP::agregarAtributoMulti(LDAPMod* att, int op, CampoConfigurableMulti campoMulti){
		att->mod_op = op;
		att->mod_type = campoMulti.getNombre();
		char* valores[campoMulti.getCantidadDeValores()];
		int i = 0;
		Nodo<char*>* actual = campoMulti.getValores()->getPrimero();
		while(actual){
			valores[i++] = actual->getDato();		
			actual = actual->getSiguiente();
		}
		char** aux = valores;
		att->mod_vals.modv_strvals = aux;
	}	

	void ConexionLDAP::cambiarServer(char* nuevoHost, int nuevoPort){
		if(enSesion) unbind();
		setHost(nuevoHost);
		setPort(nuevoPort);
		inicializar(host,port);
	}

	void ConexionLDAP::inicializar(char* host, int port){
		LDAP* ld = ldap_init(host,port);
		this->ld = ld;
		enSesion = false;
		seguir = false;
		operacion = 0;		
	}
	

	int ConexionLDAP::bind(char* user, char* pass){
		if(ld == NULL) return LD_NO_INICIALIZADO;
		int resultado =	ldap_simple_bind_s(this->ld,user,pass);
		if(resultado==LDAP_SUCCESS) enSesion = true;
		return resultado;
	}

	ConexionLDAP::~ConexionLDAP(){
		unbind();
	}

	int ConexionLDAP::unbind(){
		if(!enSesion) return NO_HAY_SESION;
		if(ld == NULL) return LD_NO_INICIALIZADO;
		int resultado =	ldap_unbind(this->ld);
		if(resultado==LDAP_SUCCESS){
			enSesion = false;
			ld = NULL; //liberar recursos? se liberan en el unbind?
		}
		return resultado;
	}

	int ConexionLDAP::buscar(char* base, int scope,char* atts[]){
		LDAPMessage ** res;
		return ldap_search_s(this->ld,base,scope,NULL,atts,1,res);
	}

	char* ConexionLDAP::crearFiltro(){
		return NULL;
	}

	int ConexionLDAP::borrar(char* dn){
		return ldap_delete_s(this->ld,dn);
	}

	int ConexionLDAP::modificar(char* dn, LDAPMod* mods[]){
		return ldap_modify_s(this->ld,dn,mods);
	}

	int ConexionLDAP::agregar(char* dn,LDAPMod* atts[]){
		return ldap_add(this->ld,dn,atts);
	}

	int ConexionLDAP::comparar(char* dn,char* attr,char* value){
		return ldap_compare(this->ld,dn,attr,value);	
	}

	int ConexionLDAP::cambiarRDN(char* dn, char* newrdn){
		return ldap_modrdn(this->ld,dn,newrdn);
	}
